#ifndef __EPSILON__WIN32__WINDOW_H__
#define __EPSILON__WIN32__WINDOW_H__

#include <windows.h>

/**
 * Information specific to Win32 windows.
 *
 */
class eWindowParametersWin32 : public eWindowParameters {
public:
  HINSTANCE         instance;    ///< Win32 parent process handle.
  WNDPROC           window_proc; ///< Ptr. to a custom window proc.  (If NULL, Epsilon's default window proc. will be used)

  /// Default constructor
  eWindowParametersWin32 (void) {
    eWindowParameters ();

    flags   |= E_WF_WIN32;
  }
};

/**
 * API specific window internals (WIN32)
 *
 */
class eWindowWin32 : eWindowInternals {
  friend class eEngine; 
  friend class eWindow;
protected:
  bool create   (const eWindowParameters& parameters, eWindow* window); ///< Create the window and perform default initialization
  bool recreate (const eWindowParameters& parameters);                  ///< Recreate the window (that is, change render context properties on the fly...)
  bool destroy  (void);                                                 ///< Destroy the window and perform all cleanup

  void move          (const int& left, const int& top); ///< Move the window to the specified left and top coordinates
  void move_client   (const int& left, const int& top); ///< Move the client region of the window
  void resize        (const int& x,    const int& y);   ///< Resize the window to the specified x and y dimensions
  void resize_client (const int& x,    const int& y);   ///< Resize the client region of the window

  void show          (int cmd);                         ///< Allows you to show or hide the window.

  void update_rect   (void);                            ///< Causes the engine to requery the dimensions from the Window Manager...

  void show_cursor    (bool show);                    ///< Show or Hide the Window Manager's cursor.
  void set_cursor_pos (int x, int y);                 ///< Set the WM's logical cursor pos, from client coords.

  const eWindowHandle
       getNativeWindowHandle (void); ///< Returns a Win32 window handle.

  LRESULT CALLBACK InternalWindowProc ( HWND    hWnd,      // Window Handle
                                        UINT    uMsg,      // Message
                                        WPARAM  wParam,    // wParam
                                        LPARAM  lParam );  // lParam

  static LRESULT CALLBACK GlobalWindowProc ( HWND    hWnd,      // Window Handle
                                             UINT    uMsg,      // Message
                                             WPARAM  wParam,    // wParam
                                             LPARAM  lParam );  // lParam

  static void Think (void); ///< Handle the Win32 Message Pump

  HWND          hWndRender;  ///< Our viewport(s) are in this window
  HINSTANCE     hInstance;   ///< Our application instance (if any)

  DWORD         dwExStyle;   ///< Window Style Ex
  DWORD         dwStyle;     ///< Window Style

  WNDPROC       WindowProc;  ///< Window Message Pump Callback
  eWindowString WindowClass; ///< Unique window class name

  DEVMODE       dmOriginal;  ///< Stores the original window mode.
                              //  (Used for windowed/fullscreen mode switches.)
};

/**
 * A special class that encapsulates Win32 HWND handles.
 *
 */
class eHWND {
public:
  eHWND (const eWindowHandle handle) {
    hwnd = *(HWND*)&handle;
  }

  eHWND (HWND handle) {
    hwnd = handle;
  }

  operator HWND (void) {
    return hwnd;
  }

private:
  HWND hwnd;
};

#endif /* __EPSILON__WIN32__WINDOW_H__ */